/**
 * @Author: 陈瑞鹏
 * @Date:   2022-09-23 11:09:17
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2022-12-05 17:48:31
 */
import ScrollViewPlus from "./ScrollViewPlus";
import { SceneManager } from "../manager/SceneManager";

export default class ScrollViewCtr {

  private static _ins: ScrollViewCtr = null;

  public static ins() {

    if (this._ins == null) {
      this._ins = new ScrollViewCtr();
    }
    return this._ins;
  }


  /**
   * @param scrollViewPlus      滚动组件
   * @param contentNode         内容节点
   * @param arr                 数据数组
   * @param prefab              预制体
   * @param componentName       脚本名称
   * @param transverseNum       横向放置几个
   * @param transverseInterval  横向间隔
   * @param verticalInterval    竖向间隔
   */
  async drawScroll(
    scrollViewPlus: ScrollViewPlus,
    contentNode: cc.Node,
    arr: Array<any>,
    prefab: cc.Prefab,
    componentName: string,
    transverseNum: number = 1,
    transverseInterval: number = 0,
    verticalInterval: number = 0,
    isAnchorCenter: boolean = true,
  ) {

    SceneManager.getInstance().pushLayer('UILoadingLayer');

    let childs: Array<cc.Node> = contentNode.children;

    for (let k: number = 0; k < childs.length; k++) {

      childs[k].active = k < arr.length ? true : false;

      childs[k].off(cc.Node.EventType.TOUCH_END);
    }

    await this.executePreFrame(
      this._getItemGenerator(
        contentNode,
        arr,
        prefab,
        componentName,
        transverseNum,
        transverseInterval,
        verticalInterval,
        isAnchorCenter,
      ), 1)

    scrollViewPlus.optDc();

    SceneManager.getInstance().removeLayer('UILoadingLayer')
  }

  /**
   * 分帧执行 Generator 逻辑
   * @param generator   生成器
   * @param duration    持续时间（ms），每次执行Generator的操作时，
   * 最长可持续执行时长。
   */
  private executePreFrame(generator: Generator, duration: number) {

    return new Promise((resolve, reject) => {

      let gen = generator;
      //创建执行函数
      let execute = () => {

        //执行之前，先记录开始时间
        let startTime = new Date().getTime();

        //然后一直从Generator中获取已经拆分好的代码段出来执行
        for (let iter = gen.next(); ; iter = gen.next()) {

          //判断是否已经执行完所有Generator的小代码段，如果是的话，那么就表示
          //任务完成
          if (iter == null || iter.done) {

            resolve(null);

            return;
          }

          //每执行完一段小代码段，都检查一下是否已经超过我们分配的本帧。
          //这些小代码段最大可执行时间 
          if (new Date().getTime() - startTime > duration) {

            //如果超过了，那么本帧就不再执行，开定时器，让下一帧再执行
            setTimeout(() => {
              execute();
            }, 16)

            return;
          }
        }
      }

      execute();
    });
  }

  private *_getItemGenerator(
    contentNode: cc.Node,
    arr: Array<any>,
    prefab: cc.Prefab,
    componentName: string,
    transverseNum: number = 1,
    transverseInterval: number = 0,
    verticalInterval: number = 0,
    isAnchorCenter: boolean = true,
  ) {

    yield this._initScrollViewItemPrefab(
      contentNode,
      arr,
      prefab,
      componentName,
      transverseNum,
      transverseInterval,
      verticalInterval,
      isAnchorCenter,
    )

  }

  private _initScrollViewItemPrefab(
    contentNode: cc.Node,
    arr: Array<any>,
    prefab: cc.Prefab,
    componentName: string,
    transverseNum: number = 1,
    transverseInterval: number = 0,
    verticalInterval: number = 0,
    isAnchorCenter: boolean = true,
  ) {

    let childs: Array<cc.Node> = contentNode.children;

    let preY: number = 0;

    for (let i: number = 0; i < arr.length; i++) {

      let pre: cc.Node = null;

      if (!childs[i]) {

        pre = cc.instantiate(prefab);

        pre.name = i + "";

        contentNode.addChild(pre);

        pre.opacity = 0;

      } else {

        pre = childs[i];

      }

      setTimeout(() => {
        let preCont: any = pre.getComponent(componentName);

        preCont.drawUi(arr[i]);

      }, 30 * i);

      let posX = ((i % transverseNum) - transverseNum / 2) * (pre.width + transverseInterval) + (pre.width + transverseInterval) / 2;

      let posY = 0 - (pre.height / 2 + (pre.height + verticalInterval) * Math.floor(i / transverseNum));

      // if (i == 0 && isAnchorCenter) {

      //   posY -= pre.height / 2;
      // }

      pre.setPosition(posX, posY);
      // preY = posY - (pre.height + verticalInterval);
    }

    if (contentNode.children.length > 0) {

      contentNode.height = (contentNode.children[0].height + verticalInterval) * Math.ceil(arr.length / transverseNum) + 50;
      // contentNode.height = Math.abs(preY)
      contentNode.width = (contentNode.children[0].width + transverseInterval) * transverseNum + 50;
    }
  }
}